//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using OpenLS.Core;
using OpenLS.Spreadsheet.Extensibility;
using OpenLS.Spreadsheet.Formats;
using OpenLS.Spreadsheet.Internals;

namespace OpenLS.Spreadsheet
{
    partial class Worksheet
    {
        
        internal PropertyChangedEventHandler DimensionPropertyChanged;

        /// <summary>
        /// Add a table to the worksheet
        /// </summary>
        /// <param name="range">The range where the table will be added</param>
        /// <param name="tableStyle">The table style</param>
        /// <returns>The newly created table</returns>
        public Table AddTable(Range range, TableStyle tableStyle, string strTableName, string strComment, bool isPublic, bool isReadOnly, bool allowsUpdate, bool allowsDelete, bool allowsInsert)
        {
            Contract.Requires(range != null);
            if (range == null)
                throw new ArgumentNullException("range");
            if (range.Worksheet != this)
                throw new ArgumentException("range");
            foreach (var table in _tables)
            {
                if ((!table.IsLocal) && (Range.Intersects(table.Range, range)))
                    throw new InvalidOperationException("range intesects table");
            }
            using (Workbook.CreateUndoScope(StringTable.Table))
            {
   
                
                var table = new Table(range) {Style = tableStyle};
                table.IsLocal = false;
                table.IsPublic = isPublic;
                table.IsReadOnly = isReadOnly;
                table.AllowsUpdate = allowsUpdate;
                table.AllowsDelete = allowsDelete;
                table.AllowsInsert = allowsInsert;

                range.Worksheet.Unmerge(range);
                if (Workbook.UndoEnabled)
                    Workbook.UndoManager.Add(new TableAddedUndoUnit(this, table));
                _tables.Add(table);


                SetupTable(table, strTableName, strComment);
                return table;
            }
        }

        public Table AddTable(Range range, TableStyle tableStyle, string strTableName, string strComment)
        {
            Contract.Requires(range != null);
            if (range == null)
                throw new ArgumentNullException("range");
            if (range.Worksheet != this)
                throw new ArgumentException("range");
            foreach (var table in _tables)
            {
                if (Range.Intersects(table.Range, range))
                    throw new InvalidOperationException("range intesects table");
            }
            using (Workbook.CreateUndoScope(StringTable.Table))
            {


                var table = new Table(range) { Style = tableStyle };
                table.IsLocal = true;
                table.IsPublic = false;
                table.IsReadOnly = false;
                table.AllowsUpdate = true;
                table.AllowsDelete = true;
                table.AllowsInsert = true;

                range.Worksheet.Unmerge(range);
                if (Workbook.UndoEnabled)
                    Workbook.UndoManager.Add(new TableAddedUndoUnit(this, table));
                _tables.Add(table);


                SetupTable(table, strTableName, strComment);
                return table;
            }
        }

        private string strBuildJsonTableDefinition(Range range)
        {
            string strJsonTable = "";
            return strJsonTable;
        }

        internal void RemoveTable(Table table)
        {
            if (!_tables.Contains(table))
                return;
#if DEBUG
           //\\ table.IsDeleted = true;
#endif
            using (Workbook.CreateUndoScope(StringTable.Table))
            {
                if (Workbook.UndoEnabled)
                    Workbook.UndoManager.Add(new TableRemovedUndoUnit(this, table));
                table.UnhookEvents();
                _tables.Remove(table);
            }
        }

        static IEnumerable<string> GetColumnNames (int index)
        {
            string prefix = "Column" + index;
            yield return prefix;
            for (int j = 1;; j++)
                yield return prefix + j;
        }
        private static void SetupTable(Table table, string strTableName, string strComment)
        {
            JsonDataTableFormat aJsonTableFormat = new JsonDataTableFormat(strTableName);
            aJsonTableFormat.Comment = strComment;
            aJsonTableFormat.IsPublic = table.IsPublic;
            aJsonTableFormat.AllowsUpdate = table.AllowsUpdate;
            aJsonTableFormat.AllowsInsert = table.AllowsInsert;
            aJsonTableFormat.AllowsUpdate = table.AllowsUpdate;
            aJsonTableFormat.IsReadOnly = table.IsReadOnly;

            var used = new HashListNoDuplicate<string>();
            int index = 0;
            foreach (Range range in table.Range.GetColumnRanges(RangeType.Dynamic))
            {
                index++;
                Cell cell = range[0, 0];
                TableColumn column = table.Columns[index - 1];
                object value = cell.Value;
                if (value is string)
                {
                    var stringValue = (string)value;
                    if (stringValue == "Column" + index)
                    {
                        column.Name = stringValue;

                        continue;
                    }
                }
                if (value == null || used.Contains(value.ToString()))
                {
                    foreach (string columnName in GetColumnNames(index))
                    {
                        if (used.Contains(columnName))
                            continue;
                        cell.Value = columnName;
                        used.Add(columnName);
                        column.Name = columnName;
                        break;
                    }
                }
                else
                {
                    used.Add(value.ToString());
                    column.Name = value.ToString();
                }
                aJsonTableFormat.AddColumn(column.Name, "");
            }

            
            int rowCount = 0;
            int colCount = 0;
            foreach (Range rowRange in table.Range.GetRowRanges(RangeType.Dynamic))
            {
                colCount = 0;
                foreach (Range range in rowRange.GetColumnRanges(RangeType.Dynamic))
                {
                    if (rowCount > 0)
                    { 
                        Cell cell = range[0, colCount];
                        object value = cell.Value;
                        Format cellFormat = cell.Format;
                        aJsonTableFormat.AddCellValueType(colCount, value, cellFormat);
                    }
                    colCount++;
                }
                rowCount++;
            }
            aJsonTableFormat.TableDisplayRowVisibleSize = rowCount;

            table.JsonTableDefinition = aJsonTableFormat;
            
            //   table.UnhookEvents();
            //   table.HookEvents();
        }

        internal void NotifyDimensionPropertyChanged (Dimension dim, string propertyName)
        {
            var e = DimensionPropertyChanged;
            if (e != null)
                e(dim, new PropertyChangedEventArgs(propertyName));
        }
    }
}
